home *** CD-ROM | disk | FTP | other *** search
- #ifndef XADMASTER_TAR_C
- #define XADMASTER_TAR_C
-
- /* Programmheader
-
- Name: Tar.c
- Main: xadmaster
- Versionstring: $VER: Tar.c 1.10 (12.08.2001)
- Author: SDI
- Distribution: Freeware
- Description: Tar file archiver client
-
- 1.0 07.09.98 : first version
- 1.1 29.06.99 : now uses master free stuff
- 1.2 29.08.99 : now uses xfi_DataPos
- 1.3 15.09.99 : also strips / from TF_DIR entries
- 1.4 11.08.00 : cleaner design
- 1.5 20.11.00 : octtonum read one byte less than specified
- 1.6 17.12.00 : octtonum now accepts spaces at end also
- 1.7 25.03.01 : now uses xadAddFileEntry()
- 1.8 27.05.01 : added support for longname extension
- 1.9 01.07.01 : added support for second longname type
- 1.10 12.08.01 : added device and fifo support
- */
-
- #include <proto/xadmaster.h>
- #include <dos/dos.h>
- #include <exec/memory.h>
- #include "SDI_compiler.h"
- #define SDI_TO_ANSI
- #include "SDI_ASM_STD_protos.h"
-
- #ifndef XADMASTERFILE
- #define Tar_Client FirstClient
- #define NEXTCLIENT 0
- #define XADMASTERVERSION 11
- UBYTE version[] = "$VER: Tar 1.10 (12.08.2001)";
- #endif
- #define TAR_VERSION 1
- #define TAR_REVISION 10
-
- struct TarHeader
- { /* byte offset */
- UBYTE th_Name[100]; /* 0 */
- UBYTE th_Mode[8]; /* 100 */
- UBYTE th_UserID[8]; /* 108 */
- UBYTE th_GroupID[8]; /* 116 */
- UBYTE th_Size[12]; /* 124 */
- UBYTE th_MTime[12]; /* 136 */
- UBYTE th_Checksum[8]; /* 148 */
- UBYTE th_Typeflag; /* 156 */
- UBYTE th_LinkName[100]; /* 157 */
- UBYTE th_Magic[6]; /* 257 */
- UBYTE th_Version[2]; /* 263 */
- UBYTE th_UserName[32]; /* 265 */
- UBYTE th_GroupName[32]; /* 297 */
- UBYTE th_DevMajor[8]; /* 329 */
- UBYTE th_DevMinor[8]; /* 337 */
- UBYTE th_Prefix[155]; /* 345 */
- UBYTE th_Pad[12]; /* 500 */
- };
-
- /* Values used in Typeflag field. */
- #define TF_FILE '0' /* Regular file */
- #define TF_AFILE '\0' /* Regular file */
- #define TF_LINK '1' /* Link */
- #define TF_SYM '2' /* Reserved - but GNU tar uses this for links... */
- #define TF_CHAR '3' /* Character special */
- #define TF_BLOCK '4' /* Block special */
- #define TF_DIR '5' /* Drawer */
- #define TF_FIFO '6' /* FIFO special */
- #define TF_CONT '7' /* Reserved */
- #define TF_LONGLINK 'K' /* longlinkname block, preceedes the full block */
- #define TF_LONGNAME 'L' /* longname block, preceedes the full block */
-
- static ULONG octtonum(STRPTR oct, LONG width, LONG *ok)
- {
- ULONG i = 0;
-
- while(*oct == ' ' && width--)
- ++oct;
-
- if(!*oct)
- *ok = 0;
- else
- {
- while(width-- && *oct >= '0' && *oct <= '7')
- i = (i*8)+*(oct++)-'0';
-
- while(*oct == ' ' && width--)
- ++oct;
-
- if(width > 0 && *oct) /* an error, set error flag */
- *ok = 0;
- }
-
- return i;
- }
-
- static BOOL checktarsum(struct TarHeader *th)
- {
- LONG sc, i;
- ULONG uc, checks;
-
- i = 1;
- checks = octtonum(th->th_Checksum, 8, &i);
- if(!i)
- return 0;
-
- for(i = sc = uc = 0; i < 512; ++i)
- {
- sc += ((BYTE *) th)[i];
- uc += ((UBYTE *) th)[i];
- }
-
- for(i = 148; i < 156; ++i)
- {
- sc -= ((BYTE *) th)[i];
- uc -= ((UBYTE *) th)[i];
- }
- sc += 8 * ' ';
- uc += 8 * ' ';
-
- if(checks != uc && checks != (ULONG) sc)
- return 0;
- return 1;
- }
-
- ASM(BOOL) Tar_RecogData(REG(d0, ULONG size), REG(a0, STRPTR data),
- REG(a6, struct xadMasterBase *xadMasterBase))
- {
- if(data[0] > 0x1F && checktarsum((struct TarHeader *) data))
- return 1;
- else
- return 0;
- }
-
- ASM(LONG) Tar_GetInfo(REG(a0, struct xadArchiveInfo *ai),
- REG(a6, struct xadMasterBase *xadMasterBase))
- {
- struct TarHeader th;
- struct xadFileInfo *fi;
- LONG err = 0, size, ok, a, b, d, i, pos;
- STRPTR longname = 0, longlink = 0, name, link;
-
- while(!err && ai->xai_InPos < ai->xai_InSize && !(err = xadHookAccess(XADAC_READ, sizeof(struct TarHeader), &th, ai)))
- {
- if(!th.th_Name[0])
- break;
- ok = checktarsum(&th); /* check checksum and init ok */
- size = octtonum(th.th_Size, 12, &ok);
-
- pos = ai->xai_InPos;
- if(ok && th.th_Typeflag == TF_LONGNAME)
- {
- if((longname = xadAllocVec(size, MEMF_ANY)))
- {
- if(!(err = xadHookAccess(XADAC_READ, size, longname, ai)))
- {
- size %= 512;
- if(size)
- err = xadHookAccess(XADAC_INPUTSEEK, 512-size, 0, ai);
- }
- }
- else
- err = XADERR_NOMEMORY;
- }
- else if(ok && th.th_Typeflag == TF_LONGLINK)
- {
- if((longlink = xadAllocVec(size, MEMF_ANY)))
- {
- if(!(err = xadHookAccess(XADAC_READ, size, longlink, ai)))
- {
- size %= 512;
- if(size)
- err = xadHookAccess(XADAC_INPUTSEEK, 512-size, 0, ai);
- }
- }
- else
- err = XADERR_NOMEMORY;
- }
- else if(ok && (th.th_Typeflag == TF_FILE || th.th_Typeflag == TF_AFILE ||
- th.th_Typeflag == TF_DIR || th.th_Typeflag == TF_SYM ||
- th.th_Typeflag == TF_LINK || th.th_Typeflag == TF_BLOCK ||
- th.th_Typeflag == TF_CHAR || th.th_Typeflag == TF_FIFO))
- {
- name = longname ? longname : th.th_Name;
- link = longlink ? longlink : (th.th_LinkName[0] ? th.th_LinkName : 0);
- a = strlen(name) + 1;
-
- if(name[a-2] == '/')
- {
- if(th.th_Typeflag == TF_AFILE || th.th_Typeflag == TF_FILE || th.th_Typeflag == TF_DIR)
- {
- name[--a-1] == 0;
- th.th_Typeflag = TF_DIR;
- }
- }
-
- if(!longname && th.th_Prefix[0])
- a += strlen(th.th_Prefix)+1;
-
- b = link ? 1 + strlen(link) : 0;
- i = th.th_UserName[0] ? 1 + strlen(th.th_UserName) : 0;
- d = th.th_GroupName[0] ? 1 + strlen(th.th_GroupName) : 0;
-
- if(!(fi = (struct xadFileInfo *) xadAllocObject(XADOBJ_FILEINFO,
- XAD_OBJNAMESIZE, a+b+i+d, TAG_DONE)))
- err = XADERR_NOMEMORY;
- else
- {
- fi->xfi_DataPos = pos;
- fi->xfi_Flags = XADFIF_SEEKDATAPOS;
- if(th.th_Typeflag == TF_LINK || th.th_Typeflag == TF_SYM)
- fi->xfi_Flags |= XADFIF_LINK;
- else if(th.th_Typeflag == TF_DIR)
- {
- fi->xfi_Flags |= XADFIF_DIRECTORY;
- size = 0;
- }
- else if(th.th_Typeflag == TF_FIFO)
- {
- fi->xfi_Flags |= XADFIF_EXTRACTONBUILD;
- fi->xfi_FileType = XADFILETYPE_UNIXFIFO;
- }
- else if(th.th_Typeflag == TF_BLOCK || th.th_Typeflag == TF_CHAR)
- {
- fi->xfi_Flags |= XADFIF_EXTRACTONBUILD;
- fi->xfi_FileType = th.th_Typeflag == TF_BLOCK ?
- XADFILETYPE_UNIXBLOCKDEVICE : XADFILETYPE_UNIXCHARDEVICE;
- /* do not care if this fails, as it is not that important */
- if((fi->xfi_Special = xadAllocObjectA(XADOBJ_SPECIAL, 0)))
- {
- fi->xfi_Special->xfis_Type = XADSPECIALTYPE_UNIXDEVICE;
- fi->xfi_Special->xfis_Data.xfis_UnixDevice.xfis_MajorVersion = octtonum(th.th_DevMajor, 8, &ok);
- fi->xfi_Special->xfis_Data.xfis_UnixDevice.xfis_MinorVersion = octtonum(th.th_DevMinor, 8, &ok);
- }
- }
- else
- {
- fi->xfi_Flags |= XADFIF_EXTRACTONBUILD;
- fi->xfi_CrunchSize = fi->xfi_Size = size;
- }
-
- if(!longname && th.th_Prefix[0])
- {
- STRPTR s, t;
-
- t = fi->xfi_FileName; s = th.th_Prefix;
- while(*s)
- *(t++) = *(s++);
- if(*(t-1) != '/')
- *(t++) = '/';
- s = th.th_Name;
- while(*s)
- *(t++) = *(s++);
- if(*(t-1) == '/')
- --t;
- *t = 0;
- }
- else
- xadCopyMem(name, fi->xfi_FileName, a-1);
- if(b)
- {
- fi->xfi_LinkName = fi->xfi_FileName + a;
- xadCopyMem(link, fi->xfi_LinkName, b-1);
- }
- if(i)
- {
- fi->xfi_UserName = fi->xfi_FileName + a + b;
- xadCopyMem(th.th_UserName, fi->xfi_UserName, i-1);
- }
- if(d)
- {
- fi->xfi_GroupName = fi->xfi_FileName + a + b + i;
- xadCopyMem(th.th_GroupName, fi->xfi_GroupName, d-1);
- }
- fi->xfi_OwnerUID = octtonum(th.th_UserID, 8, &ok);
- fi->xfi_OwnerGID = octtonum(th.th_GroupID, 8, &ok);
-
- xadConvertProtection(XAD_PROTUNIX, octtonum(th.th_Mode, 8, &ok),
- XAD_GETPROTFILEINFO, fi, TAG_DONE);
-
- xadConvertDates(XAD_DATEUNIX, octtonum(th.th_MTime, 12, &ok),
- XAD_MAKELOCALDATE, 1, XAD_GETDATEXADDATE, &fi->xfi_Date, TAG_DONE);
-
- if(th.th_Typeflag == TF_FILE || th.th_Typeflag == TF_AFILE)
- size = (size+511)&~511;
- else
- size = 0;
-
- err = xadAddFileEntry(fi, ai, XAD_SETINPOS, ai->xai_InPos+size, TAG_DONE);
- }
- if(th.th_Typeflag != TF_LONGNAME && longname)
- {
- xadFreeObjectA(longname, 0); longname = 0;
- }
- }
- }
-
- if(longname)
- xadFreeObjectA(longname, 0);
-
- if(err)
- {
- ai->xai_Flags |= XADAIF_FILECORRUPT;
- ai->xai_LastError = err;
- }
-
- return (ai->xai_FileInfo ? 0 : err);
- }
-
- ASM(LONG) Tar_UnArchive(REG(a0, struct xadArchiveInfo *ai),
- REG(a6, struct xadMasterBase *xadMasterBase))
- {
- return xadHookAccess(XADAC_COPY, ai->xai_CurFile->xfi_Size, 0, ai);
- }
-
- const struct xadClient Tar_Client = {
- NEXTCLIENT, XADCLIENT_VERSION, XADMASTERVERSION, TAR_VERSION, TAR_REVISION,
- 512, XADCF_FILEARCHIVER|XADCF_FREEFILEINFO|XADCF_FREESPECIALINFO, XADCID_TAR, "Tar",
- (BOOL (*)()) Tar_RecogData, (LONG (*)()) Tar_GetInfo,
- (LONG (*)()) Tar_UnArchive, 0};
-
- #endif /* XADMASTER_TAR_C */
-